package com.thinkcoder.service;


import com.thinkcoder.request.ApiRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;


@Component
public class DefaultApiAuthenticateImpl {

    @Resource
    private CredentialStorage credentialStorage;

    private static final String AUTHORIZATION="authorization";

    public boolean auth(String url){
        ApiRequest apiRequest = ApiRequest.createFromFullUrl(url);
        return auth(apiRequest);
    }

    public boolean auth(ApiRequest apiRequest) {

        //从请求头中获取token
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String clientToken = request.getHeader(AUTHORIZATION);
        long clientCreateTimeStamp = apiRequest.getTimeStamp();

        //校验客户端token是否过期
        AuthToken clientAuthToken = new AuthToken(clientToken, clientCreateTimeStamp);
        if(clientAuthToken.isExpired()){
            return false;
        }

        //如果存储层没有相应密码,认证不成功
        String appKey = apiRequest.getAppKey();
        String password = credentialStorage.getPasswordByAppKey(appKey);
        if("".equals(password) || password.equals(null)){
            return false;
        }

        //生成服务端token
        Integer nonce = apiRequest.getNonce();
        String originUrl = apiRequest.getOriginUrl();
        AuthToken serverAuthToken = AuthToken.createToken(originUrl, appKey, clientCreateTimeStamp, String.valueOf(nonce));

        //判断随机数是否在集合中,如果在则为重放攻击
        List<Integer> list = Nonce.getList();
        Long lastModifyTime = Nonce.getLastModifyTime();
        Nonce.clearList(serverAuthToken.getExpiredTimeInterval());
        if(Nonce.isHasNonce(nonce)){
            return false;
        }

        //服务端token对比客户端token
        if(!serverAuthToken.isMatched(clientToken)){
            return false;
        }

        //通过后向nonce集合中添加最新的数据及修改更改时间
        Nonce.add(nonce);
        Nonce.updateLastModifyTimeStamp(System.currentTimeMillis());

        return true;
    }

}
